﻿using System;
using System.ServiceModel;


public class ServiceCaller
{
    private static string _getServiceAddress_http<ISvc>()
    {
        string isIIS = AppSettings.Get("IsIIS");

        string[] interface_name = typeof(ISvc).ToString().Split('.');
        string svrName = interface_name[interface_name.Length - 1].Substring(1);
        string addr = AppSettings.Get("BaseServiceAddress");
        if (isIIS == "True")
        {
            addr = "http://" + addr + "/" + svrName.ToLower().Replace("contract", "service") + ".svc";
        }
        else
        {
            addr = "http://" + addr + "/" + svrName + "/";
        }

        if (string.IsNullOrEmpty(addr))
        {
            throw new ArgumentNullException("未能获取Web Service地址");
        }
        return addr;
    }

    private static string _getServiceAddress_tcp<ISvc>()
    {
        string addr = AppSettings.Get("TcpServiceAddress");
        string svrName = typeof(ISvc).ToString().Split('.')[1].Substring(1);
        string isIIS = AppSettings.Get("IsIIS");
        if (isIIS == "True")
        {
            addr = "net.tcp://" + addr + "/" + svrName.ToLower().Replace("contract", "service") + ".svc";
        }
        else
        {
            addr = "net.tcp://" + addr + "/" + svrName;
        }

        if (string.IsNullOrEmpty(addr))
        {
            throw new ArgumentNullException("未能获取Web Service地址");
        }
        return addr;
    }
  
    public static void ServiceExecute<ISvc>(Action<ISvc> ac)
    {
        string addr = _getServiceAddress_http<ISvc>();
        ServiceExecute<ISvc>(addr, ac);
    }

    public static void ServiceExecute<ISvc>(string addr, Action<ISvc> ac)
    {
        using (var factory = DistributedComputingServiceClient.CreateWebChannelFactory<ISvc>(addr, null))
        {
            ISvc proxy = factory.CreateChannel();

            try
            {
                ac(proxy);
            }
            catch (EndpointNotFoundException ex)
            {
                (proxy as ICommunicationObject).Abort();
                throw ex;
            }
            catch (CommunicationException)
            {
                (proxy as ICommunicationObject).Abort();
            }
            catch (TimeoutException)
            {
                (proxy as ICommunicationObject).Abort();
            }
            catch (Exception)
            {
                (proxy as ICommunicationObject).Close(new TimeSpan(0, 0, 30));
            }
            finally
            {
                (proxy as ICommunicationObject).Close(new TimeSpan(0, 0, 30));
            }
        }
    }

    public static void TcpServiceDispatcher<ISvc>(Action<ISvc> ac)
    {
        string addr = _getServiceAddress_tcp<ISvc>();
        TcpServiceExecute<ISvc>(addr, ac);
    }

    /// <summary>
    /// net.tcp服务代理
    /// </summary>
    /// <typeparam name="ISvc"></typeparam>
    /// <param name="addr"></param>
    /// <param name="ac"></param>
    private static void TcpServiceExecute<ISvc>(string addr, Action<ISvc> ac)
    {
        using (var factory = DistributedComputingServiceClient.CreateTcpChannelFactory<ISvc>(addr, null))
        {
            ISvc proxy = factory.CreateChannel();

            try
            {
                ac(proxy);
            }
            catch (CommunicationException ex)
            {
                (proxy as ICommunicationObject).Abort();
                throw ex;
            }
            catch (TimeoutException)
            {
                (proxy as ICommunicationObject).Abort();
                throw;
            }
            catch (Exception)
            {
                (proxy as ICommunicationObject).Close();
                throw;
            }
            finally
            {
                (proxy as ICommunicationObject).Close();
            }
        }
    }


    public static void StreamServiceExecute<ISvc>(Action<ISvc> ac)
    {
        string addr = AppSettings.Get("BaseServiceAddress");
        string svrName = typeof(ISvc).ToString().Split('.')[1].Substring(1);
        addr = "http://" + addr + "/" + svrName.ToLower().Replace("contract", "service") + ".svc";

        if (string.IsNullOrEmpty(addr))
        {
            throw new ArgumentNullException("未能获取Web Service地址");
        }
        StreamServiceExecute<ISvc>(addr, ac);
    }


    public static void StreamServiceExecute<ISvc>(string addr, Action<ISvc> ac)
    {
        using (var factory = DistributedComputingServiceClient.CreateStreamChannelFactory<ISvc>(addr, null))
        {
            ISvc proxy = factory.CreateChannel();

            try
            {
                ac(proxy);
            }
            catch (CommunicationException)
            {
                (proxy as ICommunicationObject).Abort();
                throw;
            }
            catch (TimeoutException)
            {
                (proxy as ICommunicationObject).Abort();
                throw;
            }
            catch (Exception)
            {
                (proxy as ICommunicationObject).Close();
                throw;
            }
            finally
            {
                (proxy as ICommunicationObject).Close();
            }
        }


    }
}
